home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / viewers / pvquan16 / quant / virt_mem.c < prev   
C/C++ Source or Header  |  1992-11-30  |  7KB  |  235 lines

  1. /************************************************************************
  2.  *                                                                      *
  3.  *                  Copyright (c) 1991, Frank van der Hulst             *
  4.  *                          All Rights Reserved                         *
  5.  *                                                                      *
  6.  * Authors:                                                             *
  7.  *        FvdH - Frank van der Hulst (Wellington, NZ)                   *
  8.  *                                                                      *
  9.  * Versions:                                                            *
  10.  *    V1.1 910626 FvdH - QUANT released for DBW_RENDER                  *
  11.  *    V1.2 911021 FvdH - QUANT released for PoV Ray                     *
  12.  *    V1.4 920303 FvdH - Ported to GNU C                                *
  13.  *    V1.6 921023 FvdH - Produce multi-image GIFs                       *
  14.  *                     - Port to OS/2 IBM C Set/2                       *
  15.  *                                                                      *
  16.  ************************************************************************/
  17. /* virt_mem.c
  18.     "Virtual memory" for QUANT. On a PC, these routines open a disk file
  19.     for use as a virtual memory buffer for BOX structure items. The most
  20.     commonly used boxes are cached in memory. As much memory as is available
  21.     is utilised for this cache. In SCO Unix sufficient memory is simply
  22.     malloc'ed. The buffer can be up to 800K long, depending on how    many
  23.     colours are to be produced. */
  24.  
  25. #ifdef __TURBOC__
  26. #include <mem.h>
  27. #endif
  28.  
  29. #include "quant.h"
  30. #include "heckbert.h"
  31.  
  32. #ifdef __TURBOC__
  33. typedef struct {
  34.     int    num;
  35.     int    age;
  36.     int    in_use;
  37.     Box    box;
  38. } BOX_BUFF;
  39.  
  40. static FILE *box_file;
  41.  
  42. static BOX_BUFF **box_buff;
  43. #else
  44. static Box **box_buff;
  45. #endif
  46. static int num_buffs;
  47.  
  48. /* Get a box (from disk if necessary), and lock it in memory so that it
  49.     can't be swapped out again. Returns a pointer to where the box is
  50.     located in memory. */
  51.  
  52. Box *get_box(int n)
  53. {
  54. #ifdef __TURBOC__
  55. int i, oldest;
  56.     oldest = 0;
  57.     for (i = 0; i < num_buffs; i++) {
  58.         if (box_buff[i]->num == n) {
  59.             box_buff[i]->age--;
  60.             box_buff[i]->in_use = TRUE;
  61.             return &box_buff[i]->box;
  62.         } else {
  63.             if (box_buff[i]->in_use) continue;
  64.             if (box_buff[i]->age > box_buff[oldest]->age)        oldest = i;
  65.         }
  66.     }
  67.     if (box_buff[oldest]->in_use) {
  68.         printf("\nInsufficient virtual memory buffers.\n");
  69.         err_exit();
  70.     }
  71.     if (box_buff[oldest]->num != -1) {
  72.         if (fseek(box_file, (long) box_buff[oldest]->num * sizeof(Box), SEEK_SET) != 0) {
  73.             printf("\nError seeking BOX_FILE.TMP for write\n");
  74.             err_exit();
  75.         }
  76.         if (fwrite(&box_buff[oldest]->box, sizeof(Box), 1, box_file) != 1) {
  77.             printf("\nError writing BOX_FILE.TMP\n");
  78.             err_exit();
  79.         }
  80.     }
  81.     if (fseek(box_file, (long) n * sizeof(Box), SEEK_SET) != 0) {
  82.         printf("\nError seeking BOX_FILE.TMP for read\n");
  83.         err_exit();
  84.     }
  85.     if (fread(&box_buff[oldest]->box, sizeof(Box), 1, box_file) != 1) {
  86.         printf("\nError reading BOX_FILE.TMP\n");
  87.         err_exit();
  88.     }
  89.     box_buff[oldest]->num = n;
  90.     box_buff[oldest]->age = 0;
  91.     box_buff[oldest]->in_use = TRUE;
  92.     return &box_buff[oldest]->box;
  93. #else
  94.     return box_buff[n];
  95. #endif
  96. }
  97.  
  98. /* Get a box (from disk if necessary), and allow it to be swapped out again.
  99.     Returns a pointer to where the box is located in memory. */
  100.  
  101. Box *get_box_tmp(int n)
  102. {
  103. #ifdef __TURBOC__
  104. int i, oldest;
  105.  
  106.     oldest = 0;
  107.     for (i = 0; i < num_buffs; i++) {
  108.         if (box_buff[i]->num == n) {
  109.             box_buff[i]->age--;
  110.             return &box_buff[i]->box;
  111.         } else {
  112.             if (box_buff[i]->in_use) continue;
  113.             if (box_buff[i]->age > box_buff[oldest]->age)        oldest = i;
  114.         }
  115.     }
  116.     if (box_buff[oldest]->in_use) {
  117.         printf("\nInsufficient virtual memory buffers.\n");
  118.         err_exit();
  119.     }
  120.     if (box_buff[oldest]->num != -1) {
  121.         if (fseek(box_file, (long) box_buff[oldest]->num * sizeof(Box), SEEK_SET) != 0) {
  122.             printf("\nError seeking BOX_FILE.TMP for write\n");
  123.             err_exit();
  124.         }
  125.         if (fwrite(&box_buff[oldest]->box, sizeof(Box), 1, box_file) != 1) {
  126.             printf("\nError writing BOX_FILE.TMP\n");
  127.             err_exit();
  128.         }
  129.     }
  130.     if (fseek(box_file, (long) n * sizeof(Box), SEEK_SET) != 0) {
  131.         printf("\nError seeking BOX_FILE.TMP for read\n");
  132.         err_exit();
  133.     }
  134.     if (fread(&box_buff[oldest]->box, sizeof(Box), 1, box_file) != 1) {
  135.         printf("\nError reading BOX_FILE.TMP\n");
  136.         err_exit();
  137.     }
  138.     box_buff[oldest]->num = n;
  139.     box_buff[oldest]->age = 0;
  140.     return &box_buff[oldest]->box;
  141. #else
  142.     return box_buff[n];
  143. #endif
  144. }
  145.  
  146. /* Free a previously locked box so that it can be swapped out to disk. */
  147.  
  148. void free_box(int n)
  149. {
  150. #ifdef __TURBOC__
  151. int i;
  152.  
  153.     for (i = 0; i < num_buffs; i++) {
  154.         if (box_buff[i]->num == n) {
  155.             box_buff[i]->in_use = FALSE;
  156.             return;
  157.         }
  158.     }
  159. #endif
  160. }
  161.  
  162. /* Grab almost all of the remaining memory (up to the number of colours
  163.     being produced), leaving only a little for printf(), etc.
  164.  
  165.     At least 3 buffers must be available, since the program locks 2 and
  166.     then wants to load a third one to compare data.
  167.  
  168.     This routine clears box[0], which is assumed by function main() in
  169.     QUANT.C. It also writes 0's to the entire disk buffer. Initially, all
  170.     cache buffers are set to -1, unused.
  171. */
  172.  
  173. void open_box_file(int buffs_needed)
  174. {
  175. int i;
  176. #ifdef __TURBOC__
  177. unsigned long coreleft;
  178.  
  179.     coreleft = farcoreleft();
  180.     if (coreleft < 0x4000L + sizeof(BOX_BUFF) * 3) {
  181.         printf("Insufficient memory: %ld needed, %ld available\n",
  182.                     0x4000L + sizeof(BOX_BUFF) * 3, coreleft);
  183.         err_exit();
  184.     }
  185.     num_buffs = (int)((coreleft - 0x4000L) / sizeof(BOX_BUFF));
  186.     if (num_buffs > buffs_needed) num_buffs = buffs_needed;
  187.     CHECK_ALLOC(box_buff, BOX_BUFF *, num_buffs, "Box Buffer");
  188.     for (i = 0; i < num_buffs; i++)
  189.         CHECK_ALLOC(box_buff[i], BOX_BUFF, 1, "Box Buffer");
  190.     printf("%d virtual memory buffers allocated\n", num_buffs);
  191.     box_file = fopen("VIRT_MEM.TMP", "w+b");
  192.     if (box_file == NULL) {
  193.         printf("Couldn't open VIRT_MEM.TMP\n");
  194.         err_exit();
  195.     }
  196.     for (i = 0; i < num_buffs; i++) {
  197.         box_buff[i]->num    = -1;
  198.         box_buff[i]->age    = 0x7fff;
  199.         box_buff[i]->in_use = FALSE;
  200.     }
  201.  
  202.     printf("Clearing virtual memory disk buffer.\n");
  203.     memset(&box_buff[0]->box, 0, sizeof(Box));
  204.     for (i = 0; i < buffs_needed; i++) {
  205.         if (fwrite(&box_buff[0]->box, sizeof(Box), 1, box_file) != 1) {
  206.             printf("\nError writing VIRT_MEM.TMP\n");
  207.             err_exit();
  208.         }
  209.     }
  210. #else
  211.  
  212.     CHECK_ALLOC(box_buff, Box *, buffs_needed, "Box buffer");
  213.     num_buffs = buffs_needed;
  214.     for (i = 0; i < buffs_needed; i++)
  215.         CHECK_ALLOC(box_buff[i], Box, 1, "Box buffer");
  216.     printf("%d box buffers allocated\n", buffs_needed);
  217.  
  218.     for (i = 0; i < buffs_needed; i++)
  219.         memset(box_buff[i], 0, sizeof(Box));
  220. #endif
  221. }
  222.  
  223. /* Release cache buffers, and delete the disk buffer file */
  224.  
  225. void close_box_file(void)
  226. {
  227. int i;
  228.     for (i = 0; i < num_buffs; i++)     free(box_buff[i]);
  229.     free(box_buff);
  230. #ifdef __TURBOC__
  231.     fclose(box_file);
  232.     unlink("VIRT_MEM.TMP");
  233. #endif
  234. }
  235.